package com.uuah.server.context.notification;

import java.util.EventObject;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.uuah.server.endpoint.UuahEndpointURI;
import com.uuah.utils.ClassUtils;

/**
 *
 * TODO comment ...
 *
 * <p>update record:updator，update time，update content and version</p>
 * @author <a href="jonny_quan@hotmail.com">jonny</a>
 * @date 2009 2009-3-27 下午01:34:06
 * @version 1.0.0
 */
public abstract class ServerNotification extends EventObject {
	public static final int NO_ACTION_ID = Integer.MIN_VALUE;
	public static final String NO_ACTION_NAME = "none";

	public static final String TYPE_INFO = "info";
	public static final String TYPE_WARNING = "warn";
	public static final String TYPE_ERROR = "error";
	public static final String TYPE_FATAL = "fatal";

	protected static final int CONTEXT_EVENT_ACTION_START_RANGE = 100;
	protected static final int MODEL_EVENT_ACTION_START_RANGE = 200;
	protected static final int SERVICE_EVENT_ACTION_START_RANGE = 300;
	protected static final int AGENT_EVENT_ACTION_START_RANGE = 400;
	protected static final int CONNECTION_EVENT_ACTION_START_RANGE = 700;
	protected static final int MESSAGE_EVENT_ACTION_START_RANGE = 800;
	protected static final int SPACE_EVENT_ACTION_START_RANGE = 900;
	protected static final int REGISTRY_EVENT_ACTION_START_RANGE = 1000;
	protected static final int EXCEPTION_EVENT_ACTION_START_RANGE = 1100;
	protected static final int COMPONENT_EVENT_ACTION_START_RANGE = 1400;
	protected static final int CUSTOM_EVENT_ACTION_START_RANGE = 100000;

	public static final int NULL_ACTION = 0;
	public static final Object NULL_MESSAGE = "";

	public final String EVENT_NAME = ClassUtils.getClassName(getClass());

	protected long timestamp;

	protected int action = NULL_ACTION;
	private static Map actionIdToName = new ConcurrentHashMap();
	private static Map actionNameToId = new ConcurrentHashMap();

	protected String resourceIdentifier = null;

	public ServerNotification(Object message, int action) {
		this(message, action, null);
	}

	public ServerNotification(Object message, int action,
			String resourceIdentifier) {
		super((message == null ? NULL_MESSAGE : message));
		this.action = action;
		this.resourceIdentifier = resourceIdentifier;
		timestamp = System.currentTimeMillis();
	}

	public int getAction() {
		return action;
	}

	public String getResourceIdentifier() {
		return resourceIdentifier;
	}

	public long getTimestamp() {
		return timestamp;
	}

	public boolean isResourceIdentifierAnUri() {
		return UuahEndpointURI.isUuahUri(resourceIdentifier);
	}

	public String toString() {
		return EVENT_NAME + "{" + "action=" + getActionName(action)
				+ ", resourceId=" + resourceIdentifier + ", timestamp="
				+ timestamp + "}";
	}

	protected String getPayloadToString() {
		return source.toString();
	}

	public String getType() {
		return TYPE_INFO;
	}

	public String getActionName() {
		return getActionName(action);
	}

	protected static synchronized void registerAction(String name, int i) {
		String lowerCaseName = name.toLowerCase();
		Integer id = new Integer(i);
		if (actionNameToId.containsKey(lowerCaseName)) {
			throw new IllegalStateException("Action " + name
					+ " already registered");
		}
		if (actionIdToName.containsKey(id)) {
			throw new IllegalStateException("Action id " + i
					+ " already registered");
		}
		actionIdToName.put(id, lowerCaseName);
		actionNameToId.put(lowerCaseName, id);
	}

	public static String getActionName(int action) {
		if (action == NO_ACTION_ID) {
			return NO_ACTION_NAME;
		}
		Integer key = new Integer(action);
		if (actionIdToName.containsKey(key)) {
			return (String) actionIdToName.get(key);
		} else {
			throw new IllegalArgumentException("No action with id: " + action);
		}
	}

	public static int getActionId(String action) {
		String lowerCaseName = action.toLowerCase();
		if (actionNameToId.containsKey(lowerCaseName)) {
			return ((Integer) actionNameToId.get(lowerCaseName)).intValue();
		} else {
			throw new IllegalArgumentException("No action called: " + action);
		}
	}
}
